package au.edu.unsw.editingtool.global;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.StringTokenizer;
import java.util.regex.*; 

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import au.edu.unsw.editingtool.fedora.FedoraFactory;
import au.edu.unsw.editingtool.transformxml.XMLProcessor;
import org.w3c.dom.*;

public class Util {
	
	public static String join(String array[], String delimiter, String left, String right) {
		String result = "";
		
		if ((array == null) || (array.length == 0))
			return result;
		
		int i = 0;
		for (; i < array.length - 1; i++) {
			result += left + array[i] + right + delimiter;
		}
		
		result += left + array[i] + right;
		return result;
	}
	
	@SuppressWarnings("unchecked")
	public static Object splitString(String rawString, String delimiter, Object obj){
		
		String className = obj.getClass().getName();
		
		StringTokenizer token = new StringTokenizer(rawString, delimiter);
		
		while (token.hasMoreElements()) {
			String t = token.nextToken().trim();
			if (className.equals("java.util.Hashtable"))
				((Hashtable<String, String>) obj).put(t, null);					
			else if (className.equals("java.util.LinkedList"))
				((LinkedList) obj).add(t);
		}
		
		return obj;
	}
	
	public static Hashtable<String, String> getNodeListViaPath(String path, String fileToRead) throws ParserConfigurationException, SAXException, IOException, XPathExpressionException {
		DocumentBuilderFactory dom = DocumentBuilderFactory.newInstance();
		dom.setNamespaceAware(true);
		DocumentBuilder builder = dom.newDocumentBuilder();
		Document doc = builder.parse(new File(fileToRead));
		
	    doc.getDocumentElement().normalize();
	    NodeList nl = doc.getDocumentElement().getChildNodes();
	   // System.out.println("[UTIL] getNodeListViaPath : NL Length = "+nl.getLength());
	    		
		Hashtable<String, String> results = new Hashtable<String, String>();
		
		XPathFactory factory = XPathFactory.newInstance();
		XPath xpath = factory.newXPath();
		XPathExpression expr = xpath.compile(path);
		NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
		NodeList resultnodes = nodes.item(0).getChildNodes();
		
		//System.out.println("[UTIL] getNodeListViaPath : Input Path = "+path);		
		//System.out.println("[UTIL] getNodeListViaPath : Nodes Length = "+.getLength());
		//System.out.println("[UTIL] getNodeListViaPath : VALETXML = "+fileToRead);
		
		for (int i = 0; i < resultnodes.getLength(); i++)
		{
			Node nd = resultnodes.item(i);
			System.out.println("[UTIL] getNodeListViaPath = "+nd.getNodeName()+":"+nd.getTextContent());
			results.put(nd.getNodeName(), nd.getTextContent());
		}
		return results;
	}
	
	public static String transformAsLabel(String value) {
		String label[] = value.split("_");
		String result = "";
		for (int i=0; i<label.length ; i++) {
			result += Character.toUpperCase(label[i].charAt(0)) + label[i].substring(1) + " ";
		}
		return result.substring(0, result.length() - 2);
	}
	
	public static String createTempFile(String name, String suffix, String dir) throws IOException {
		File tempdir = new File(dir);
		File temp = File.createTempFile(name, suffix);
		
		// Problem using this one
		// File temp = File.createTempFile(name, suffix, dir);
		System.out.println("[UTIL] createTempFile : Temporary = "+temp.getAbsolutePath());
		return temp.getAbsolutePath();
	}
	
 
	public static String getValetXML(String sessionId, String pid, String datastreamID,
									 FedoraFactory fedora, PropertyReader reader, String servletContext) 
	throws IOException, EditingToolException, TransformerConfigurationException, TransformerException, SAXException {
		
		String file = "";
		String valetXML = "";
		XMLProcessor processor = new XMLProcessor();
		
		//System.out.println("[UTIL] getValetXML : TEMPDIR = "+GlobalConstant.tempFileDir);
		file = Util.createTempFile(sessionId, "xml", GlobalConstant.tempFileDir);
		
		byte[] xml = fedora.getDatastream(pid, datastreamID);
		FileOutputStream fos = new FileOutputStream(file);
		fos.write(xml);
		
		valetXML = Util.createTempFile(sessionId, "out", GlobalConstant.tempFileDir);
		
		Hashtable<String, String> properties = getProperties(reader, GlobalConstant.TRANSFORM);
		
		processor.setOutFile(valetXML);
		processor.setXml(file);
		
		String xslfile= properties.get("root") + GlobalConstant.fileSeparator +
		 properties.get("metadata") + GlobalConstant.fileSeparator + 
		 properties.get("tovalet");
				
		//System.out.println("[UTIL] getValetXML : XSL = "+xslfile);
		String FS = System.getProperty("file.separator");		
		
		processor.setXsl(servletContext+xslfile);
		//System.out.println("[UTIL] getValetXML : XML is set!");
		processor.xmlProcessor("");
		//System.out.println("[UTIL] getValetXML : Transformation finished!");
		
		return valetXML;
	}

	public static String getHTTPRequestData(HttpServletRequest request, String mask) {
		if ((request.getParameter(mask) == null) || 
			(request.getParameter(mask).trim().length() == 0))
			return (String) request.getAttribute(mask);
		return request.getParameter(mask);
	}
	
	public static Hashtable<String, String> getProperties(PropertyReader reader, 
													String filter) throws IOException {
		reader.clean();
		reader.setFilter(filter);
		reader.retrieveProperties();
		return reader.getProperties();
	}	
}
